package l1j.server.server.model;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;

import l1j.server.server.datatables.MagicDollTable;
import l1j.server.server.model.Instance.L1DollInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_SPMR;
import l1j.server.server.serverpackets.S_SkillSound;
import l1j.server.server.templates.L1MagicDoll;
import l1j.server.server.utils.Random;
import l1j.server.server.utils.collections.Maps;

public class L1DollList {


	private L1PcInstance _master ;
	private Map<Integer , L1DollInstance> _dollList;


	public L1DollList(final L1PcInstance pc){
		_master = pc;
		_dollList =  Maps.newConcurrentMap();
	}

	public int size(){
		return _dollList.size();
	}
	public boolean isEmpty(){
		return _dollList.isEmpty();
	}

	public L1DollInstance getDollByItem(final int objid){
		for(final L1DollInstance doll : getAllDolls()){
			if(doll.getItemObjId() == objid){
				return doll;
			}
		}
		return null;
	}

	private Collection<L1DollInstance> _allDollValues;

	/**取得所擁有的娃娃*/
	public Collection<L1DollInstance> getAllDolls() {
		Collection<L1DollInstance> vs = _allDollValues;
		return (vs != null) ? vs : (_allDollValues = Collections.unmodifiableCollection(_dollList.values()));
	}

	/**新增娃娃至列表*/
	public void addDoll(final L1DollInstance doll){
		if (doll == null) {
			throw new NullPointerException();
		}
		_dollList.put(doll.getId(), doll);
		newDoll(doll);
		getAddDmgChance();
	}

	/**將娃娃從列表中移除*/
	public void removeDoll(final L1DollInstance doll){
		if (doll == null) {
			throw new NullPointerException();
		}
		_dollList.remove(doll.getId());
		deleteDoll(doll);
		getAddDmgChance();
	}

	private void newDoll(final L1DollInstance doll){
		final L1MagicDoll temp = MagicDollTable.getInstance().getTemplate(doll.getItemId());
		if(temp == null){
			return;
		}
		final int makeItemId = temp.getMakeItemId();
		if(makeItemId >0){
			_master.startItemMakeByDoll(temp.getMakeItemTime() , makeItemId);
		}
		if(hasTimeHprByDoll()){
			_master.startHpRegenerationByDoll();
		}
		if(hasTimeMprByDoll()){
			_master.startMpRegenerationByDoll();
		}
		/**娃娃增加防禦率opqlo改寫**/
		_master.addAc(doll.getAc());
		_master.addStr(doll.getStr());
		_master.addDex(doll.getDex());
		_master.addCon(doll.getCon());
		_master.addInt(doll.getInt());
		_master.addWis(doll.getWis());
		_master.addCha(doll.getCha());
		_master.addMr(doll.getMr());
		_master.setRegistStone(temp.getRegistStone());
		_master.setRegistSustain(temp.getRegistStun());
		_master.setRegistBlind(temp.getRegistBlind());
		_master.setRegistFreeze(temp.getRegistFreeze());
		_master.setRegistSleep(temp.getRegistSleep());
		_master.addWind(doll.getWind());//TODO 風屬性防禦
		_master.addWater(doll.getWater());//TODO 水屬性防禦
		_master.addFire(doll.getFire());//TODO 火屬性防禦
		_master.addEarth(doll.getEarth());//TODO 地屬性防禦
		_master.sendPackets(new S_SPMR(_master));
		/**0=普通、1=不死系、2=惡魔系、3=BOSS系、4=亡靈系、5=狼人系、6=龍系、7=人系*/
		_master.addEthncityDmg(0, (temp.get普通() / 100D));
		_master.addEthncityDmg(1, (temp.get不死() / 100D));
		_master.addEthncityDmg(2, (temp.get惡魔() / 100D));
		_master.addEthncityDmg(3, (temp.getBOSS() / 100D));
		_master.addEthncityDmg(4, (temp.get亡靈() / 100D));
		_master.addEthncityDmg(5, (temp.get狼人() / 100D));
		_master.addEthncityDmg(6, (temp.get龍() / 100D));
		_master.addEthncityDmg(7, (temp.get人() / 100D));
		_master.addAttrDmg(1, (temp.get地() / 100D ));
		_master.addAttrDmg(2, (temp.get火() / 100D ));
		_master.addAttrDmg(4, (temp.get水() / 100D ));
		_master.addAttrDmg(8, (temp.get風() / 100D ));
		_master.add金幣率(temp.get金幣加倍());
		_master.addDroprate(temp.get掉寶加倍());
		this.adddmgEvasion(temp.getDmgEvasionChance());//迴避機率
		this.addBowHit(temp.getBowHit());//娃娃遠距離命中opqlo改寫
		this.addHit(temp.getHit());//娃娃近距離命中opqlo改寫
		this.addWeightReduction(temp.getWeightReduction());
		/**娃娃HPR、MPR opqlo改寫**/
		this.addHpr(temp.getHpr());
		this.addMpr(temp.getMpr());
		_dmg += temp.getDmg();
		_dmgchance+= temp.getDmgChance();
		_bowdmg += temp.getBowDmg();
		_bowdmgchance +=  temp.getBowDmgChance();
		_reductionM += temp.getDmgReduction();
		_reductionchance += temp.getDmgReductionChance();
		_exp += (int)(temp.getExpRate()*100);
		_expchance += temp.getExpRateChance();
		_eva += temp.getDmgEvasionChance();
	}


	private void deleteDoll(final L1DollInstance doll){
		final L1MagicDoll temp = MagicDollTable.getInstance().getTemplate(doll.getItemId());
		if(temp == null){
			return;
		}
		final int makeItemId = temp.getMakeItemId();
		if(makeItemId >0){
			_master.stopItemMakeByDoll( makeItemId);
		}
		if(hasTimeHprByDoll()){
			_master.stopHpRegenerationByDoll();
		}
		if(hasTimeMprByDoll()){
			_master.stopHpRegenerationByDoll();
		}
		_master.addAc(-doll.getAc());
		_master.addStr(-doll.getStr());
		_master.addDex(-doll.getDex());
		_master.addCon(-doll.getCon());
		_master.addInt(-doll.getInt());
		_master.addWis(-doll.getWis());
		_master.addCha(-doll.getCha());
		_master.setRegistStone(-temp.getRegistStone());
		_master.setRegistSustain(-temp.getRegistStun());
		_master.setRegistBlind(-temp.getRegistBlind());
		_master.setRegistFreeze(-temp.getRegistFreeze());
		_master.setRegistSleep(-temp.getRegistSleep());

		_master.addWind(-doll.getWind()); //TODO 風屬性防禦
		_master.addWater(-doll.getWater());//TODO 水屬性防禦
		_master.addFire(-doll.getFire());//TODO 火屬性防禦
		_master.addEarth(-doll.getEarth());//TODO 地屬性防禦

		_master.addMr(-doll.getMr());


		/**0=普通、1=不死系、2=惡魔系、3=BOSS系、4=亡靈系、5=狼人系、6=龍系、7=人系*/
		_master.addEthncityDmg(0, -(temp.get普通() / 100D));
		_master.addEthncityDmg(1, -(temp.get不死() / 100D));
		_master.addEthncityDmg(2, -(temp.get惡魔() / 100D));
		_master.addEthncityDmg(3, -(temp.getBOSS() / 100D));
		_master.addEthncityDmg(4, -(temp.get亡靈() / 100D));
		_master.addEthncityDmg(5, -(temp.get狼人() / 100D));
		_master.addEthncityDmg(6, -(temp.get龍() / 100D));
		_master.addEthncityDmg(7, -(temp.get人() / 100D));
		_master.addAttrDmg(1, -(temp.get地() / 100D ));
		_master.addAttrDmg(2, -(temp.get火() / 100D ));
		_master.addAttrDmg(4, -(temp.get水() / 100D ));
		_master.addAttrDmg(8, -(temp.get風() / 100D ));
		_master.add金幣率(-temp.get金幣加倍());
		_master.addDroprate(-temp.get掉寶加倍());
		this.adddmgEvasion(-temp.getDmgEvasionChance());//迴避機率
		this.addBowHit(-temp.getBowHit());//娃娃遠距離命中opqlo改寫
		this.addHit(-temp.getHit());//娃娃近距離命中opqlo改寫
		this.addWeightReduction(-temp.getWeightReduction());
		/**娃娃HPR、MPR opqlo改寫**/
		this.addHpr(-temp.getHpr());
		this.addMpr(-temp.getMpr());
		doll.deleteMe();
		_dmg -= temp.getDmg();
		_dmgchance-= temp.getDmgChance();
		_bowdmg -= temp.getBowDmg();
		_bowdmgchance -=  temp.getBowDmgChance();
		_reductionM -= temp.getDmgReduction();
		_reductionchance -= temp.getDmgReductionChance();
		_exp -= (int)(temp.getExpRate()*100);
		_expchance -= temp.getExpRateChance();
		_eva -= temp.getDmgEvasionChance();
	}

	public int _dmg , _dmgchance , _bowdmg , _bowdmgchance ,_reductionM , _reductionchance , _exp , _expchance , _eva;


	private int getAddDmgChance(){
		int HighChance = 0;
		final Collection<L1DollInstance> dolllist = getAllDolls();
		if(dolllist == null || dolllist.isEmpty()){
			return HighChance;
		}
		for (final L1DollInstance dolls : dolllist) {
			L1MagicDoll temp = MagicDollTable.getInstance().getTemplate(dolls.getItemId());
			HighChance = Math.max( HighChance,temp.getDmgChance());
		}
		return HighChance;
	}
	public boolean hasTimeHprByDoll(){
		boolean isTrue = false;
		final Collection<L1DollInstance> dolllist = getAllDolls();
		if(dolllist == null || dolllist.isEmpty()){
			return isTrue;
		}
		for (final L1DollInstance dolls : dolllist) {
			isTrue = dolls.hasHprTime();
		}
		return isTrue;
	}

	public boolean hasTimeMprByDoll(){
		boolean isTrue = false;
		final Collection<L1DollInstance> dolllist = getAllDolls();
		if(dolllist == null || dolllist.isEmpty()){
			return isTrue;
		}
		for (final L1DollInstance dolls : dolllist) {
			isTrue = dolls.hasMprTime();
		}
		return isTrue;
	}

	public int getDollHprTime() { // 魔法娃娃額外追加的HPR恢復間隔時間
		int hpr =0;
		final Collection<L1DollInstance> dolllist = getAllDolls();
		if(dolllist == null || dolllist.isEmpty()){
			return hpr;
		}
		for (final L1DollInstance dolls : dolllist) {
			hpr += dolls.getHprForTime();
		}
		return hpr;
	}

	public int getDollMprTime() { // 魔法娃娃額外追加的MPR恢復間隔時間
		int mpr =0;
		final Collection<L1DollInstance> dolllist = getAllDolls();
		if(dolllist == null || dolllist.isEmpty()){
			return mpr;
		}
		for (final L1DollInstance dolls : dolllist) {
			mpr += dolls.getMprForTime();
		}
		return mpr;
	}

	/** 娃娃HPR、MPR opqlo改寫 **/
	private int _hpr1, _mpr1;
	/** 娃娃重量輕減opqlo改寫 **/
	private int _weightreduction;
	/** 娃娃增加防禦率opqlo改寫 **/
	private int _ac;
	/** 娃娃增加迴避率opqlo改寫 **/
	private int _dmgEvasion;
	/** 娃娃增加減傷opqlo改寫 **/
	private int _reductionChance, _reduction;
	/** 娃娃近距離命中opqlo改寫 **/
	private int _Hit;
	/** 娃娃遠距離命中opqlo改寫 **/
	private int _bowHit;
	private final short[] _6Values = new short[6];
	/** 1=str 2=dex 3=con 4=int 5=wis 6=cha */
	public void add6Values(final int i, final short value) {
		this._6Values[i - 1] += value;
	}
	/** 1=str 2=dex 3=con 4=int 5=wis 6=cha */
	public short get6Values(final int type) {
		return this._6Values[type - 1];
	}

	public void addAc(final int i) {
		this._ac += i;
	}

	public void addBowHit(final int i) {
		this._bowHit += i;
	}

	public void addHit(final int i) {
		this._Hit += i;
	}

	public void addHpr(final int i) {
		this._hpr1 += i;
	}

	public void addMpr(final int i) {
		this._mpr1 += i;
	}


	public void addWeightReduction(final int i) {
		this._weightreduction += i;
	}

	public int getAc() {
		return this._ac;
	}

	public int getBowHit() {
		return this._bowHit;
	}

	public int getdmgEvasion() {
		return this._dmgEvasion;
	}

	/**取得各娃娃機率加成數*/
	public double getExpAddRate(){
		double exprate = 1;
		final Collection<L1DollInstance> dolllist = getAllDolls();
		if(dolllist == null || dolllist.isEmpty()){
			return exprate;
		}
		for (final L1DollInstance dolls : dolllist) {
			L1MagicDoll temp = MagicDollTable.getInstance().getTemplate(dolls.getItemId());
			final int chance = Random.nextInt(100)+1;
			if(temp.getExpRateChance() >= chance){
				exprate += temp.getExpRate();
			}
		}
		return exprate;
	}


	/** 娃娃增加遠距離傷害opqlo改寫 **/
	public int getBowDmg(){
		int dmg =0;
		final Collection<L1DollInstance> dolllist = getAllDolls();
		if(dolllist == null || dolllist.isEmpty()){
			return dmg;
		}
		for (final L1DollInstance dolls : dolllist) {
			L1MagicDoll temp = MagicDollTable.getInstance().getTemplate(dolls.getItemId());
			final int chance = Random.nextInt(100)+1;
			if(temp.getBowDmgChance() >= chance){
				dmg += temp.getBowDmg();
			}
		}
		if(dmg >0){
			_master.sendPacketsX8(new S_SkillSound(_master.getId(), 6319));
		}
		return dmg;
	}


	/** 娃娃增加近距離傷害opqlo改寫 **/
	public int getDmg(){
		int dmg =0;
		final Collection<L1DollInstance> dolllist = getAllDolls();
		if(dolllist == null || dolllist.isEmpty()){
			return dmg;
		}
		for (final L1DollInstance dolls : dolllist) {
			L1MagicDoll temp = MagicDollTable.getInstance().getTemplate(dolls.getItemId());
			final int chance = Random.nextInt(100)+1;
			if(temp.getDmgChance() >= chance){
				dmg += temp.getDmg();
			}
		}
		if(dmg >0){
			_master.sendPacketsX8(new S_SkillSound(_master.getId(), 6319));
		}
		return dmg;
	}

	/** 娃娃增加減傷opqlo改寫 **/
	public int getDamageReduction() {
		int reduction =0;
		final Collection<L1DollInstance> dolllist = getAllDolls();
		if(dolllist == null || dolllist.isEmpty()){
			return reduction;
		}
		for (final L1DollInstance dolls : dolllist) {
			L1MagicDoll temp = MagicDollTable.getInstance().getTemplate(dolls.getItemId());
			final int chance = Random.nextInt(100)+1;
			if(temp.getDmgReductionChance() >= chance){
				reduction += temp.getDmgReduction(); 
			}
		}
		return reduction;
	}


	public int getHit() {
		return this._Hit;
	}

	public int getHpr() {
		return this._hpr1;
	}

	public int getMpr() {
		return this._mpr1;
	}

	public int getReduction() {
		return this._reduction;
	}

	public int getReductionChance() {
		return this._reductionChance;
	}

	public int getWeightReduction() {
		return this._weightreduction;
	}

	public void adddmgEvasion(final int i) {
		this._dmgEvasion += i;
	}

	public void setReduction(final int i) {
		this._reduction = i;
	}

	public void setReductionChance(final int i) {
		this._reductionChance = i;
	}
}
